import collections
import json

from django.core.cache import cache
from django.http import JsonResponse
from django.shortcuts import render

from TaskSaasAPP.hash_map_util import HashMap
from web.models import BreakdownStory, Issues


def kanban_context(request, project_id):
    # todo 优先级字段 合并正序
    story_queryset = BreakdownStory.objects.filter(project_id=project_id).filter(status__in=[1, 2, 3, 4, 5, 6, 9])
    issue_queryset = Issues.objects.filter(project_id=project_id).filter(status__in=[1, 2, 3, 4, 5])
    pool_list = []
    confirm_list = []
    developing_list = []
    done_list = []
    dev_list = []
    prod_list = []
    story_list = story_queryset_format(story_queryset, project_id)
    for s in story_list:
        if s[7] == 'pool':
            pool_list.append(s)
        elif s[7] == 'confirm':
            confirm_list.append(s)
        elif s[7] == 'done':
            done_list.append(s)
        elif s[7] == 'dev':
            dev_list.append(s)
        elif s[7] == 'prod':
            prod_list.append(s)
        elif s[7] == 'developing':
            developing_list.append(s)
    issue_list = issue_queryset_format(issue_queryset, project_id)
    for i in issue_list:
        if i[7] == 'pool':
            pool_list.append(i)
        elif i[7] == 'confirm':
            confirm_list.append(i)
        elif i[7] == 'developing':
            developing_list.append(i)
        elif i[7] == 'done':
            done_list.append(i)
        elif i[7] == 'dev':
            dev_list.append(i)
        elif i[7] == 'prod':
            prod_list.append(i)
    # 如果没有缓存创建缓存
    if not cache.get('myKanbanOrderCache_' + project_id):
        if_no_order_cache_then_cache(project_id,
                                     pool_list, confirm_list, developing_list, done_list, dev_list, prod_list)
    else:
        order_cache = json.loads(cache.get('myKanbanOrderCache_' + str(project_id)))
        i = 0
        pool_list_order_dict = order_cache['pool_list']
        print('pool_list_order_dict', pool_list_order_dict)
        for p in pool_list:
            order = pool_list_order_dict.get(p[3] + '-' + str(p[0]))
            print(p[3] + '-' + str(p[0]) + ':' + str(order))
            pool_list.remove(p)
            p += (order,)
            pool_list.insert(i, p)
            i += 1
        i = 0
        confirm_list_order_dict = order_cache['confirm_list']
        for con in confirm_list:
            order = confirm_list_order_dict.get(con[3] + '-' + str(con[0]))
            confirm_list.remove(con)
            con += (order,)
            confirm_list.insert(i, con)
            i += 1
        i = 0
        developing_list_order_dict = order_cache['developing_list']
        for de in developing_list:
            order = developing_list_order_dict.get(de[3] + '-' + str(de[0]))
            developing_list.remove(de)
            de += (order,)
            developing_list.insert(i, de)
            i += 1
        i = 0
        done_list_order_dict = order_cache['done_list']
        for d in done_list:
            order = done_list_order_dict.get(d[3] + '-' + str(d[0]))
            done_list.remove(d)
            d += (order,)
            done_list.insert(i, d)
            i += 1
        i = 0
        dev_list_order_dict = order_cache['dev_list']
        for dev in dev_list:
            order = dev_list_order_dict.get(dev[3] + '-' + str(dev[0]))
            dev_list.remove(dev)
            dev += (order,)
            dev_list.insert(i, dev)
            i += 1
        i = 0
        prod_list_order_dict = order_cache['prod_list']
        for prod in prod_list:
            order = prod_list_order_dict.get(prod[3] + '-' + str(prod[0]))
            prod_list.remove(prod)
            prod += (order,)
            prod_list.insert(i, prod)
            i += 1
        i = 0
        pool_list.sort(key=lambda x: (x[8] is not None, x[8]), reverse=False)
        confirm_list.sort(key=lambda x: (x[8] is not None, x[8]), reverse=False)
        developing_list.sort(key=lambda x: (x[8] is not None, x[8]), reverse=False)
        done_list.sort(key=lambda x: (x[8] is not None, x[8]), reverse=False)
        dev_list.sort(key=lambda x: (x[8] is not None, x[8]), reverse=False)
        prod_list.sort(key=lambda x: (x[8] is not None, x[8]), reverse=False)
        need_refresh_cache_flag = False
        pl_order_is_none = False
        if pool_list:
            print('pool_list >>', pool_list[0])
            pl_order_is_none = True if pool_list[0][8] is None else False
            need_refresh_cache_flag = pl_order_is_none
        cl_order_is_none = False
        if confirm_list:
            print('confirm_list >>', confirm_list[0])
            cl_order_is_none = True if confirm_list[0][8] is None else False
            need_refresh_cache_flag = cl_order_is_none
        dl_order_is_none = False
        if developing_list:
            print('developing_list >>', developing_list[0])
            dl_order_is_none = True if developing_list[0][8] is None else False
            need_refresh_cache_flag = dl_order_is_none
        done_order_is_none = False
        if done_list:
            print('done_list >>', done_list[0])
            done_order_is_none = True if done_list[0][8] is None else False
            need_refresh_cache_flag = done_order_is_none
        dev_order_is_none = False
        if dev_list:
            print('dev_list >>', dev_list[0])
            dev_order_is_none = True if dev_list[0][8] is None else False
            need_refresh_cache_flag = dev_order_is_none
        prod_order_is_none = False
        if prod_list:
            print('prod_list >>', prod_list[0])
            prod_order_is_none = True if prod_list[0][8] is None else False
            need_refresh_cache_flag = prod_order_is_none
        if need_refresh_cache_flag:
            refresh_order_cache_selection(project_id,
                                          pool_list if pl_order_is_none else None,
                                          confirm_list if cl_order_is_none else None,
                                          developing_list if dl_order_is_none else None,
                                          done_list if done_order_is_none else None,
                                          dev_list if dev_order_is_none else None,
                                          prod_list if prod_order_is_none else None)
    context = {
        'pool_list': pool_list,
        'confirm_list': confirm_list,
        'developing_list': developing_list,
        'done_list': done_list,
        'dev_list': dev_list,
        'prod_list': prod_list,
    }
    return context


def kanban(request, project_id):
    context = kanban_context(request, project_id)
    print('context:', context)
    return render(request, 'web/kanban.html', context)


def story_queryset_format(story_queryset, project_id):
    if story_queryset:
        return [(story.id, story.story_name, story.get_status_display(),
                 'story',
                 '/manage/' + str(project_id) + '/breakdownstory/detail/' + str(story.id),
                 story.create_datetime,
                 '',
                 'dev' if story.version == 1
                 else 'prod' if story.version == 2
                 else 'pool' if story.status in [1, 3, 4]
                 else 'confirm' if story.status in [2, 5]
                 else 'done' if story.status in [6]
                 else 'developing' if story.status in [9]
                 else '') for story in story_queryset]
    return []


def issue_queryset_format(issue_queryset, project_id):
    if issue_queryset:
        return [(issue.issue_id, issue.subject, issue.get_status_display(),
                 'task',
                 '/manage/' + str(project_id) + '/issues/detail/' + str(issue.issue_id),
                 issue.create_datetime,
                 'bug' if issue.issues_type_id == 3 else '',
                 'dev' if issue.version == 1
                 else 'prod' if issue.version == 2
                 else 'pool' if issue.status in [1, 3]
                 else 'confirm' if issue.status in [4]
                 else 'developing' if issue.status in [2]
                 else 'done' if issue.status in [5]
                 else '') for issue in issue_queryset]
    return []


def refresh_order_cache_selection(project_id, pool_list, confirm_list, developing_list, done_list, dev_list, prod_list):
    pool_list_order_dict = collections.OrderedDict()
    if pool_list:
        pool_list.sort(key=lambda x: x[5], reverse=True)
        pool_list.sort(key=lambda x: x[6], reverse=True)
        i = 0
        for p in pool_list:
            pool_list_order_dict[p[3] + '-' + str(p[0])] = i
            pool_list.remove(p)
            p += (i,)
            pool_list.insert(i, p)
            i += 1
        i = 0
    confirm_list_order_dict = collections.OrderedDict()
    if confirm_list:
        confirm_list.sort(key=lambda x: x[5], reverse=True)
        confirm_list.sort(key=lambda x: x[6], reverse=True)
        i = 0
        for con in confirm_list:
            confirm_list_order_dict[con[3] + '-' + str(con[0])] = i
            confirm_list.remove(con)
            con += (i,)
            confirm_list.insert(i, con)
            i += 1
        i = 0
    developing_list_order_dict = collections.OrderedDict()
    if developing_list:
        developing_list.sort(key=lambda x: x[5], reverse=True)
        developing_list.sort(key=lambda x: x[6], reverse=True)
        i = 0
        for de in developing_list:
            developing_list_order_dict[de[3] + '-' + str(de[0])] = i
            developing_list.remove(de)
            de += (i,)
            developing_list.insert(i, de)
            i += 1
        i = 0
    done_list_order_dict = collections.OrderedDict()
    if done_list:
        done_list.sort(key=lambda x: x[5], reverse=True)
        done_list.sort(key=lambda x: x[6], reverse=True)
        i = 0
        for d in done_list:
            done_list_order_dict[d[3] + '-' + str(d[0])] = i
            done_list.remove(d)
            d += (i,)
            done_list.insert(i, d)
            i += 1
        i = 0
    dev_list_order_dict = collections.OrderedDict()
    if dev_list:
        dev_list.sort(key=lambda x: x[5], reverse=True)
        dev_list.sort(key=lambda x: x[6], reverse=True)
        i = 0
        for dev in dev_list:
            dev_list_order_dict[dev[3] + '-' + str(dev[0])] = i
            dev_list.remove(dev)
            dev += (i,)
            dev_list.insert(i, dev)
            i += 1
        i = 0
    prod_list_order_dict = collections.OrderedDict()
    if prod_list:
        prod_list.sort(key=lambda x: x[5], reverse=True)
        prod_list.sort(key=lambda x: x[6], reverse=True)
        i = 0
        for prod in prod_list:
            prod_list_order_dict[prod[3] + '-' + str(prod[0])] = i
            prod_list.remove(prod)
            prod += (i,)
            prod_list.insert(i, prod)
            i += 1
        i = 0
    old_cache = cache.get('myKanbanOrderCache' + '_' + str(project_id))
    if old_cache:
        old_cache = json.loads(old_cache)
        if not pool_list_order_dict:
            pool_list_order_dict = old_cache['pool_list']
        if not confirm_list_order_dict:
            confirm_list_order_dict = old_cache['confirm_list']
        if not developing_list_order_dict:
            developing_list_order_dict = old_cache['developing_list']
        if not done_list_order_dict:
            done_list_order_dict = old_cache['done_list']
        if not dev_list_order_dict:
            dev_list_order_dict = old_cache['dev_list']
        if not prod_list_order_dict:
            prod_list_order_dict = old_cache['prod_list']
    order_cache = {
        'pool_list': pool_list_order_dict,
        'confirm_list': confirm_list_order_dict,
        'developing_list': developing_list_order_dict,
        'done_list': done_list_order_dict,
        'dev_list': dev_list_order_dict,
        'prod_list': prod_list_order_dict,
    }
    # order_cache = cache.get('myKanbanOrderCache_' + project_id)
    # print('order_cache::',order_cache)
    cache.set('myKanbanOrderCache' + '_' + str(project_id), json.dumps(order_cache), timeout=None)


def if_no_order_cache_then_cache(project_id, pool_list, confirm_list, developing_list, done_list, dev_list, prod_list):
    pool_list.sort(key=lambda x: x[5], reverse=True)
    pool_list.sort(key=lambda x: x[6], reverse=True)
    confirm_list.sort(key=lambda x: x[5], reverse=True)
    confirm_list.sort(key=lambda x: x[6], reverse=True)
    developing_list.sort(key=lambda x: x[5], reverse=True)
    developing_list.sort(key=lambda x: x[6], reverse=True)
    done_list.sort(key=lambda x: x[5], reverse=True)
    done_list.sort(key=lambda x: x[6], reverse=True)
    dev_list.sort(key=lambda x: x[5], reverse=True)
    dev_list.sort(key=lambda x: x[6], reverse=True)
    prod_list.sort(key=lambda x: x[5], reverse=True)
    prod_list.sort(key=lambda x: x[6], reverse=True)
    i = 0
    pool_list_order_dict = collections.OrderedDict()
    for p in pool_list:
        pool_list_order_dict[p[3] + '-' + str(p[0])] = i
        pool_list.remove(p)
        p += (i,)
        pool_list.insert(i, p)
        i += 1
    i = 0
    confirm_list_order_dict = collections.OrderedDict()
    for con in confirm_list:
        confirm_list_order_dict[con[3] + '-' + str(con[0])] = i
        confirm_list.remove(con)
        con += (i,)
        confirm_list.insert(i, con)
        i += 1
    i = 0
    developing_list_order_dict = collections.OrderedDict()
    for de in developing_list:
        developing_list_order_dict[de[3] + '-' + str(de[0])] = i
        developing_list.remove(de)
        de += (i,)
        developing_list.insert(i, de)
        i += 1
    i = 0
    done_list_order_dict = collections.OrderedDict()
    for d in done_list:
        done_list_order_dict[d[3] + '-' + str(d[0])] = i
        done_list.remove(d)
        d += (i,)
        done_list.insert(i, d)
        i += 1
    i = 0
    dev_list_order_dict = collections.OrderedDict()
    for dev in dev_list:
        dev_list_order_dict[dev[3] + '-' + str(dev[0])] = i
        dev_list.remove(dev)
        dev += (i,)
        dev_list.insert(i, dev)
        i += 1
    i = 0
    prod_list_order_dict = collections.OrderedDict()
    for prod in prod_list:
        prod_list_order_dict[prod[3] + '-' + str(prod[0])] = i
        prod_list.remove(prod)
        prod += (i,)
        prod_list.insert(i, prod)
        i += 1
    i = 0
    order_cache = {
        'pool_list': pool_list_order_dict,
        'confirm_list': confirm_list_order_dict,
        'developing_list': developing_list_order_dict,
        'done_list': done_list_order_dict,
        'dev_list': dev_list_order_dict,
        'prod_list': prod_list_order_dict,
    }
    # order_cache = cache.get('myKanbanOrderCache_' + project_id)
    # print('order_cache::',order_cache)
    cache.set('myKanbanOrderCache' + '_' + str(project_id), json.dumps(order_cache), timeout=None)


key_val_map = HashMap()
key_val_map._put("storyTaskPool", "pool_list")
key_val_map._put("confirmAssignIng", "confirm_list")
key_val_map._put("developing", "developing_list")
key_val_map._put("doneAndTesting", "done_list")
key_val_map._put("toBeRelease", "dev_list")
key_val_map._put("released", "prod_list")

key_status_map = HashMap()

key_status_map._put("storyTaskPool_task", [1])
key_status_map._put("confirmAssignIng_task", [4])
key_status_map._put("developing_task", [2])
key_status_map._put("doneAndTesting_task", [5])
key_status_map._put("toBeRelease_task", 1)
key_status_map._put("released_task", 2)

key_status_map._put("storyTaskPool_story", [1])
key_status_map._put("confirmAssignIng_story", [2])
key_status_map._put("developing_story", [9])
key_status_map._put("doneAndTesting_story", [6])
key_status_map._put("toBeRelease_story", 1)
key_status_map._put("released_story", 2)


def kanban_refresh(request, project_id):
    if request.method == 'POST':
        source_id = request.POST.get('sourceId')
        target_id = request.POST.get('targetId')
        move_node = request.POST.get('moveNode')
        print('source_id', source_id, 'target_id', target_id, 'move_node', move_node)
        move_node_arr = move_node.split('-')
        node = str(move_node_arr[0]) + '-' + str(move_node_arr[1])
        add_index = int(move_node_arr[3])
        node_type = str(move_node_arr[0])
        node_id = str(move_node_arr[1])
        print('node', node)
        order_cache = cache.get('myKanbanOrderCache_' + project_id)
        print('order_cache', order_cache)
        old_cache = cache.get('myKanbanOrderCache' + '_' + str(project_id))
        if old_cache:
            old_cache = json.loads(old_cache)
            source_list_key = key_val_map.get(source_id)
            print('source_list_key', source_list_key)
            source_order_dict = old_cache[str(source_list_key)]
            target_list_key = key_val_map.get(target_id)
            print('target_list_key', target_list_key)
            target_order_dict = old_cache[str(target_list_key)]
            source_order_dict.pop(str(node), None)
            for key in list(source_order_dict.keys()):
                source_order_dict[key] = list(source_order_dict.values()).index(source_order_dict[key])
            print('source_order_dict>>', source_order_dict)
            print('add_index', add_index)
            # 获取当前字典的最大索引值
            target_max_index = 0
            if target_order_dict:
                target_max_index = max(target_order_dict.values())

            # 如果给定的索引大于最大索引值，直接添加新键值对
            if add_index > target_max_index:
                target_order_dict[str(node)] = add_index
            else:
                # 更新大于给定索引的所有键的值
                for key in list(target_order_dict.keys()):
                    if target_order_dict[key] >= add_index:
                        target_order_dict[key] += 1

                # 插入新键值对
                target_order_dict[str(node)] = add_index
            print('target_order_dict', target_order_dict)
            old_cache[str(target_list_key)] = target_order_dict
            old_cache[str(source_list_key)] = source_order_dict
            print('str(target_list_key)', str(target_list_key))
            print('str(source_list_key)', str(source_list_key))
            cache_set = cache.set('myKanbanOrderCache' + '_' + str(project_id), json.dumps(old_cache),
                                  timeout=None)
            print('cache_set', cache_set)
            if target_id != source_id:
                to_be_status_or_version, val_type = key_status_map.get_and_type(target_id + '_' + node_type)
                print('val_type:', val_type)
                if node_type == 'task':
                    task = Issues.objects.filter(issue_id=node_id, project_id=project_id).first()
                    print('task', task)
                    if task and to_be_status_or_version:
                        print('type (tobe) ', type(to_be_status_or_version))
                        if isinstance(to_be_status_or_version, list):
                            task.status = to_be_status_or_version[0]
                            task.version = None
                        else:
                            task.version = to_be_status_or_version
                        task.save()
                if node_type == 'story':
                    story = BreakdownStory.objects.filter(id=node_id, project_id=project_id).first()
                    if story and to_be_status_or_version:
                        if isinstance(to_be_status_or_version, list):
                            story.status = to_be_status_or_version[0]
                            story.version = None
                        else:
                            story.version = to_be_status_or_version
                        story.save()
    return JsonResponse({'status': 1})
